import { Callout, Tabs } from 'nextra/components';
import { Widget } from '@/components/demo/widget.tsx';
import LinkBadge from '@/components/ui/link-badge/link-badge.tsx';
import LinkBadgeGroup from '@/components/ui/link-badge/link-badge-group.tsx';

# Portal

A portal renders a portal widget that "floats" on top of a child widget.

<LinkBadgeGroup>
    <LinkBadge label="API Reference" href="https://pub.dev/documentation/forui/latest/forui.foundation/FPortal-class.html"/>
</LinkBadgeGroup>

<Callout type="info">
  This widget is typically used to create other high-level widgets, e.g., [popover](../overlay/popover) or
  [tooltip](../overlay/tooltip). You should prefer those high-level widgets unless you're creating a custom widget.
</Callout>

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='portal' query={{}} height={500}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    class PortalPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) => FPortal(
        spacing: const FPortalSpacing(8),
        viewInsets: const EdgeInsets.all(5),
        portalBuilder: (context, _) => Container(
          decoration: BoxDecoration(
            color: context.theme.colors.background,
            border: Border.all(color: context.theme.colors.border),
            borderRadius: BorderRadius.circular(4),
          ),
          padding: const EdgeInsets.only(left: 20, top: 14, right: 20, bottom: 10),
          child: SizedBox(
            width: 288,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Dimensions', style: context.theme.typography.base),
                const SizedBox(height: 7),
                Text(
                  'Set the dimensions for the layer.',
                  style: context.theme.typography.sm.copyWith(
                    color: context.theme.colors.mutedForeground,
                    fontWeight: FontWeight.w300,
                  ),
                ),
                const SizedBox(height: 15),
                for (final (label, value) in [('Width', '100%'), ('Max. Width', '300px')]) ...[
                  Row(
                    children: [
                      Expanded(child: Text(label, style: context.theme.typography.sm)),
                      Expanded(flex: 2, child: FTextField(initialText: value)),
                    ],
                  ),
                  const SizedBox(height: 7),
                ],
              ],
            ),
          ),
        ),
        builder: (context, controller, _) => FButton(onPress: controller.toggle, child: const Text('Portal')),
      );
    }
    ```

  </Tabs.Tab>
</Tabs>

## Usage

### `FPortal(...)`

```dart copy
FPortal(
  controller: OverlayPortalController(),
  spacing: FPortalSpacing.zero,
  overflow: FPortalOverflow.flip,
  offset: Offset.zero,
  portalConstraints: const FAutoWidthPortalConstraints(),
  portalAnchor: Alignment.topCenter,
  childAnchor: Alignment.bottomCenter,
  viewInsets: EdgeInsets.zero,
  barrier: Container(color: Colors.blue),
  portalBuilder: (context, controller) => const Text('portal'),
  builder: (context, controller, child) => child!,
  child: const Text('child'),
);
```

## Visualization

<Widget name='portal-visualization' query={{}} height={600}/>
